import json
import requests

from rest_framework import exceptions

from system.services import setting_service
from connection.services import connection_service
from plugin.models import PluginInstallRecord
from plugin.tasks import install_plugin, uninstall_plugin
from libs.enums import PluginInstallState


class PluginService:
    PLUGIN_SOURCE_APP_ID_KEY = 'PLUGIN_SOURCE_APP_ID'

    def set_source_app(self, source_app):
        setting_service.set(self.PLUGIN_SOURCE_APP_ID_KEY, source_app)

    def get_source_app(self):
        source_app = setting_service.get(self.PLUGIN_SOURCE_APP_ID_KEY)
        if source_app:
            source_app = int(source_app)
        return source_app

    def get_plugins(self, request):
        source_app = self.get_source_app()
        if not source_app:
            raise exceptions.ValidationError({'error': '请先配置源应用'})
        server, headers = connection_service.get_server_and_headers_by_partner_id(source_app)
        api = f'{server}/openapi/plugin/plugins'

        key = request.query_params.get('key')
        name = request.query_params.get('name')
        publisher = request.query_params.get('publisher')
        installed = request.query_params.get('installed')
        keys = None
        installed_queryset = PluginInstallRecord.objects.all()
        installed_keys = []
        installed_status_map = {}
        for instance in installed_queryset:
            installed_keys.append(instance.key)
            installed_status_map[instance.key] = instance.state

        if installed == 'true':
            keys = installed_keys
        request_data = {
            'key': key,
            'name': name,
            'publisher': publisher,
            'keys': keys
        }
        response = requests.post(url=api, json=request_data, headers=headers)
        if response.status_code != 200:
            raise exceptions.ValidationError({'error': '源应用可能存在异常，请稍后再试'})
        data = json.loads(response.content)
        for item in data['items']:
            item['state'] = installed_status_map.get(item['key'], 'not_install')
        return data

    def install(self, key, git_url, name):
        instance, _ = PluginInstallRecord.objects.get_or_create(
            key=key,
            defaults={
                'git_url': git_url,
                'name': name
            }
        )
        install_plugin.delay(instance.id)

    def uninstall(self, key):
        instance = PluginInstallRecord.objects.filter(key=key).first()
        instance.state = PluginInstallState.UNINSTALLING.value
        instance.save()
        if not instance:
            return
        uninstall_plugin.delay(instance.id)

    def exists_processing_plugins(self):
        ''' 是否存在正在安装或卸载的扩展
        '''
        processing_states = [
            PluginInstallState.PENDING.value,
            PluginInstallState.INSTALLING.value,
            PluginInstallState.UNINSTALLING.value,
        ]
        return PluginInstallRecord.objects.filter(state__in=processing_states).exists()


plugin_service = PluginService()
